package com.example.demo.exception;

import com.alibaba.fastjson.JSONObject;
import com.example.demo.response.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.util.Assert;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.nio.file.AccessDeniedException;
import java.util.List;

@RestControllerAdvice
@Slf4j
@Order(1)
public class BizExceptionHandler {

    static String message = "系统繁忙，请稍后再试！";

    /**
     * 自定义异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BizException.class)
    @ResponseStatus(HttpStatus.OK)
    public R checkedException(BizException e) {
        if (isErrorDescription(e, e.getMessage())) {
            return getMessage(e.getMessage());
        }
        log.error(e.getMessage(), e);
        return R.failed(e.getCode(), e.getMessage());
    }

    private R getMessage(String message) {
        return R.failed(JSONObject.parseObject(message.substring(message.indexOf("{"), message.indexOf("}") + 1)).get("error_description").toString());
    }

    private boolean isErrorDescription(Exception e, String message) {
        if (StringUtils.isNotBlank(message) && message.contains("error_description")) {
            return true;
        }
        return false;
    }

    /**
     * 处理业务校验过程中碰到的非法参数异常 该异常基本由{@link Assert}抛出
     *
     * @param e 参数校验异常CheckExceptionHandler
     * @return API返回结果对象包装后的错误输出结果
     * @see Assert#hasLength(String, String)
     * @see Assert#hasText(String, String)
     * @see Assert#isTrue(boolean, String)
     * @see Assert#isNull(Object, String)
     * @see Assert#notNull(Object, String)
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.OK)
    public R handleIllegalArgumentException(IllegalArgumentException e) {
        log.error(e.getMessage(), e);
        return R.failed(e.getMessage());
    }

    /**
     * validation Exception
     *
     * @param exception
     * @return R
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseStatus(HttpStatus.OK)
    public R handleBodyValidException(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        return R.failed(fieldErrors.get(0).getDefaultMessage());
    }

    /**
     * validation Exception (以form-data形式传参)
     *
     * @param e
     * @return R
     */
    @ExceptionHandler({BindException.class})
    @ResponseStatus(HttpStatus.OK)
    public R bindExceptionHandler(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        log.error(e.getMessage(), e);
        return R.failed(fieldErrors.get(0).getDefaultMessage());
    }


    /**
     * 权限接口校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.OK)
    public R accessDeniedExceptionHandler(AccessDeniedException e) {
        return R.failed("您没有权限，请联系管理员");
    }
}
